package ULHT.LIG2N1.RC.CLIENTINTERFACE;

import ULHT.LIG2N1.RC.CLIENT.ClientTokenAndState;
import ULHT.LIG2N1.RC.CLIENT.GetAnswer;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.io.*;
import java.net.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JRootPane;
import javax.swing.WindowConstants;

public class MenuPrincipal extends javax.swing.JFrame {

    private static int TCPport = 6500, maxConnections = 0, UDPport = 9031, UDPmulticastPort = 9013;
    private static String hostAddress = "localhost";
    private String multicastGroup = "230.0.0.1";
    private boolean desclassificado = false;
    private Socket TCPsocket;
    private DatagramSocket datagramListener;
    private MulticastSocket multicastListener;
    private ClientTokenAndState token = new ClientTokenAndState();
    private BufferedReader in;
    private PrintWriter out;
    private GUIUDPThread threadUDP;
    private GUIUDPMulticastThread threadMulticastUDP;

    public void init() {
        this.initComponents();
        this.setVisible(true);

        this.setLocationRelativeTo(getRootPane());

        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        int height = screenSize.height;
        int width = screenSize.width;
        this.setSize(width / 2, height / 2);

        // here's the part where i center the jframe on screen
        this.setLocationRelativeTo(null);
    }

    public boolean testAvailablility() {
        this.writeToServer("CHECKCONNECTION");

        if (!readFromServerEvo().equalsIgnoreCase("OK")) {
            return false;
        } else {
            return true;
        }
    }

    public boolean getQuestion() {
        try {
            String eval;
            Home questionForm = new Home(TCPsocket);

            writeToServer("PLAY");
            eval = readFromServerEvo();
            if (eval.equalsIgnoreCase("WAIT")) {
                this.CaixaFeedback.setText(readFromServerEvo());

                return false;
            } else {
                writeToServer("READY");
                readFromServerEvo();
                writeToServer("GETQUESTION");
                readFromServerEvo();
                writeToServer("READY");
                questionForm.SetPergunta(readFromServerEvo());

                //Esconde Menu Inicial
                this.setVisible(false);

                //Mostra Formulário de Perguntas
                questionForm.setVisible(true);
                questionForm.setLocationRelativeTo(getRootPane());
                questionForm.setResizable(false);
                questionForm.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
                return true;
            }

        } catch (IOException ex) {
            Logger.getLogger(MenuPrincipal.class.getName()).log(Level.SEVERE, null, ex);
        }

        return false;
    }

    /*
     * public void setMessage(String mensagem) {
     *
     * this.Txt_Menu.setText(mensagem); }
     */
    public MenuPrincipal() {

        initComponents();

    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        button1 = new java.awt.Button();
        Btn_Inscritos = new javax.swing.JButton();
        Btn_Online = new javax.swing.JButton();
        Btn_Desclassificados = new javax.swing.JButton();
        Btn_HoraServidor = new javax.swing.JButton();
        Btn_Inicio = new javax.swing.JButton();
        Btn_Respostas = new javax.swing.JButton();
        Btn_Sair = new javax.swing.JButton();
        jLabel1 = new javax.swing.JLabel();
        jScrollPane1 = new javax.swing.JScrollPane();
        CaixaFeedback = new javax.swing.JTextArea();
        BTN_Testar_Unicast = new javax.swing.JButton();
        connection = new javax.swing.JButton();

        button1.setLabel("button1");
        button1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                button1ActionPerformed(evt);
            }
        });

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setResizable(false);

        Btn_Inscritos.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
        Btn_Inscritos.setText("Participantes Inscritos");
        Btn_Inscritos.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Btn_InscritosActionPerformed(evt);
            }
        });

        Btn_Online.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
        Btn_Online.setText("Participantes Online");
        Btn_Online.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Btn_OnlineActionPerformed(evt);
            }
        });

        Btn_Desclassificados.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
        Btn_Desclassificados.setText("Participantes Desclassificados");
        Btn_Desclassificados.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Btn_DesclassificadosActionPerformed(evt);
            }
        });

        Btn_HoraServidor.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
        Btn_HoraServidor.setText("Hora Servidor");
        Btn_HoraServidor.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                Btn_HoraServidorMouseClicked(evt);
            }
        });
        Btn_HoraServidor.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Btn_HoraServidorActionPerformed(evt);
            }
        });

        Btn_Inicio.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
        Btn_Inicio.setText("Hora Inicio");
        Btn_Inicio.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Btn_InicioActionPerformed(evt);
            }
        });

        Btn_Respostas.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
        Btn_Respostas.setText("Responder");
        Btn_Respostas.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Btn_RespostasActionPerformed(evt);
            }
        });

        Btn_Sair.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
        Btn_Sair.setText("Sair");
        Btn_Sair.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                Btn_SairMouseClicked(evt);
            }
        });
        Btn_Sair.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Btn_SairActionPerformed(evt);
            }
        });

        jLabel1.setFont(new java.awt.Font("Tahoma", 3, 18)); // NOI18N
        jLabel1.setForeground(new java.awt.Color(0, 0, 204));
        jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        jLabel1.setText("Quem Quer Ser Milionário");

        CaixaFeedback.setColumns(20);
        CaixaFeedback.setEditable(false);
        CaixaFeedback.setLineWrap(true);
        CaixaFeedback.setRows(5);
        CaixaFeedback.setWrapStyleWord(true);
        CaixaFeedback.setEnabled(false);
        jScrollPane1.setViewportView(CaixaFeedback);

        BTN_Testar_Unicast.setText("Testar Unicast");
        BTN_Testar_Unicast.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                BTN_Testar_UnicastActionPerformed(evt);
            }
        });

        connection.setText("Check Connection");
        connection.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                connectionActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 251, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(0, 0, Short.MAX_VALUE))
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addComponent(BTN_Testar_Unicast, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addGroup(layout.createSequentialGroup()
                                .addGap(0, 0, Short.MAX_VALUE)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                                    .addComponent(Btn_Desclassificados, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 251, Short.MAX_VALUE)
                                    .addComponent(Btn_Sair, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                    .addComponent(Btn_Online, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 251, Short.MAX_VALUE)
                                    .addComponent(Btn_Inscritos, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 251, Short.MAX_VALUE)
                                    .addComponent(Btn_Respostas, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                    .addComponent(Btn_HoraServidor, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 251, Short.MAX_VALUE)
                                    .addComponent(Btn_Inicio, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 251, Short.MAX_VALUE)
                                    .addComponent(jLabel1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
                        .addGap(20, 20, 20))))
            .addGroup(layout.createSequentialGroup()
                .addGap(36, 36, 36)
                .addComponent(connection)
                .addGap(0, 0, Short.MAX_VALUE))
        );

        layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {Btn_Desclassificados, Btn_HoraServidor, Btn_Inicio, Btn_Inscritos, Btn_Online, Btn_Respostas, Btn_Sair});

        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabel1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(Btn_Inscritos, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(Btn_Online, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(Btn_Desclassificados, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(Btn_HoraServidor, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(Btn_Inicio, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(Btn_Respostas)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(BTN_Testar_Unicast, javax.swing.GroupLayout.PREFERRED_SIZE, 34, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(3, 3, 3)
                .addComponent(connection)
                .addGap(18, 18, 18)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 183, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(Btn_Sair, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(20, 20, 20))
        );

        layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {Btn_Desclassificados, Btn_HoraServidor, Btn_Inicio, Btn_Inscritos, Btn_Online, Btn_Respostas, Btn_Sair});

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void Btn_InscritosActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_Btn_InscritosActionPerformed
        writeToServer("WHITELIST");
        this.CaixaFeedback.setText(readFromServerEvo());
    }//GEN-LAST:event_Btn_InscritosActionPerformed

    private void Btn_HoraServidorMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_Btn_HoraServidorMouseClicked
    }//GEN-LAST:event_Btn_HoraServidorMouseClicked

    private void Btn_SairMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_Btn_SairMouseClicked
        writeToServer("QUIT");
        this.threadUDP.halt();
        this.threadMulticastUDP.halt();
        this.datagramListener = null;
        this.multicastListener = null;
        this.TCPsocket = null;
        token.quit();
        System.exit(0);
    }//GEN-LAST:event_Btn_SairMouseClicked

    private void button1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_button1ActionPerformed
    }//GEN-LAST:event_button1ActionPerformed

    private void Btn_HoraServidorActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_Btn_HoraServidorActionPerformed
        writeToServer("TIME");
        this.CaixaFeedback.setText(readFromServerEvo());
    }//GEN-LAST:event_Btn_HoraServidorActionPerformed

    private void Btn_OnlineActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_Btn_OnlineActionPerformed
        writeToServer("PLAYERS");
        this.CaixaFeedback.setText(readFromServerEvo());
    }//GEN-LAST:event_Btn_OnlineActionPerformed

    private void Btn_DesclassificadosActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_Btn_DesclassificadosActionPerformed
        writeToServer("BLACKLIST");
        this.CaixaFeedback.setText(readFromServerEvo());
    }//GEN-LAST:event_Btn_DesclassificadosActionPerformed

    private void Btn_InicioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_Btn_InicioActionPerformed
        writeToServer("NEXTGAME");
        this.CaixaFeedback.setText(readFromServerEvo());
    }//GEN-LAST:event_Btn_InicioActionPerformed

    private void Btn_SairActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_Btn_SairActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_Btn_SairActionPerformed

    private void BTN_Testar_UnicastActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_BTN_Testar_UnicastActionPerformed
        writeToServer("TESTUNICAST");
    }//GEN-LAST:event_BTN_Testar_UnicastActionPerformed

    private void Btn_RespostasActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_Btn_RespostasActionPerformed
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<String> input = executor.submit(new GetAnswer());
        boolean validInput = true;
        String resposta = null;
        long timeout = 0;
        getQuestion();
    }//GEN-LAST:event_Btn_RespostasActionPerformed

    private void connectionActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_connectionActionPerformed
        CaixaFeedback.setText("Estado da ligação: " + this.testAvailablility());
    }//GEN-LAST:event_connectionActionPerformed
    public static void main(String args[]) {

        /*
         * Set the Nimbus look and feel
         */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
            /*
         * If Nimbus (introduced in Java SE 6) is not available, stay with the
         * default look and feel. For details see
         * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(MenuPrincipal.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(MenuPrincipal.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(MenuPrincipal.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(MenuPrincipal.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /*
         * Create and display the form
         */

        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {

                MenuPrincipal menu = new MenuPrincipal();
                menu.setVisible(true);
                menu.corre();

            }
        });

    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton BTN_Testar_Unicast;
    private javax.swing.JButton Btn_Desclassificados;
    private javax.swing.JButton Btn_HoraServidor;
    private javax.swing.JButton Btn_Inicio;
    private javax.swing.JButton Btn_Inscritos;
    private javax.swing.JButton Btn_Online;
    private javax.swing.JButton Btn_Respostas;
    private javax.swing.JButton Btn_Sair;
    private javax.swing.JTextArea CaixaFeedback;
    private java.awt.Button button1;
    private javax.swing.JButton connection;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JScrollPane jScrollPane1;
    // End of variables declaration//GEN-END:variables

    private String readFromServerEvo() throws NullPointerException{

        try {
            int msgSize = 0;
            String serverReply = null;
            char[] buffer = null;
            boolean isReplying = false;
            int i = 1;
            while (!isReplying && (i <= 10)) {
                try {
                    serverReply = in.readLine();
                } catch (IOException ex) {
                    i++;
                }
                if (serverReply != null && serverReply.length() > 0) {
                    if (serverReply.isEmpty()) {
                        return null;
                    } else {
                        try {
                            msgSize = Integer.parseInt(serverReply);
                        } catch (NumberFormatException nfe) {
                            return null;
                        }
                        buffer = new char[msgSize];
                        int totalRead = 0;
                        while (totalRead < msgSize) {
                            int read = 0;
                            try {
                                read = in.read(buffer, totalRead, msgSize - totalRead);
                            } catch (IOException ex) {
                                Logger.getLogger(MenuPrincipal.class.getName()).log(Level.SEVERE, null, ex);
                            }
                            if (read == -1) {
                                return null;
                            }
                            totalRead += read;
                        }
                        isReplying = true;
                    }
                }
            }
            return new String(buffer);
        } catch (NullPointerException ex) 
{
            return null;
        }
    }

    private void writeToServer(String output) throws NullPointerException{
        if (!TCPsocket.isClosed()) {
            out.println(output);
        }
    }

    private void corre() {
        try {
            TCPsocket = new Socket(hostAddress, TCPport);
            datagramListener = new DatagramSocket(UDPport);
            multicastListener = new MulticastSocket(UDPmulticastPort);
            multicastListener.joinGroup(InetAddress.getByName(multicastGroup));
            threadUDP = new GUIUDPThread(datagramListener, this.CaixaFeedback);
            threadMulticastUDP = new GUIUDPMulticastThread(multicastListener, multicastGroup, this.CaixaFeedback, this.Btn_Respostas);
            try {
                // dois segundos de timeout até considerar que a ligação caiu
                TCPsocket.setSoTimeout(4000);
                in = new BufferedReader(new InputStreamReader(TCPsocket.getInputStream()));
                out = new PrintWriter(TCPsocket.getOutputStream(), true);
            } catch (IOException ex) {
                this.CaixaFeedback.setText("Erro de ligação ao socket!");
            }
            threadUDP.start();
            threadMulticastUDP.start();
        } catch (UnknownHostException ex) {
            this.CaixaFeedback.setText("Host desconhecido!");
        } catch (IOException ex) {
            this.CaixaFeedback.setText("Erro de ligação ao socket!");
        }
        if (!login()) {
            this.CaixaFeedback.setText("Servidor não enviou o token!");
        }
    }

    private boolean login() {

        writeToServer("HANDSHAKE");
        String msgFrmSrv = readFromServerEvo();
        if (msgFrmSrv.equalsIgnoreCase("HELLO")) {
            token.setToken(readFromServerEvo());
            return true;
        } else if (msgFrmSrv.equalsIgnoreCase("FORBIDDEN")) {
            this.CaixaFeedback.setText("Cliente proíbido pelo servidor");
            //TODO desligar o cliente?
        }
        return false;
    }
}
